home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / util / misc / VMM_src.lha / VMM / cache.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-16  |  6.9 KB  |  310 lines

  1. #include <exec/types.h>
  2. #include "defs.h"
  3.  
  4. static char rcsid [] = "$Id: cache.c,v 3.5 95/12/16 18:37:02 Martin_Apel Exp $";
  5.  
  6. PRIVATE ULONG LastAccessed = 0;
  7. PRIVATE char *WriteCache;
  8. PRIVATE BOOL *EntryValid;
  9. PRIVATE ULONG FirstSlot,
  10.               NumSlotsInCache;
  11. PRIVATE ULONG NumSlotsUsedInCache;
  12. PRIVATE ULONG NumSlotsUsed;         /* Number of overall used slots */
  13. PRIVATE ULONG BufSize;
  14.  
  15. PRIVATE void FlushCache (void);
  16.  
  17. /* This module assumes that there is no allocation of a page on disk
  18.  * between the allocation of another one and its writing to disk.
  19.  * If this is ever changed 'fault.c' will have to be changed accordingly.
  20.  */
  21.  
  22. /************************************************************************/
  23.  
  24. int InitCache (void)
  25.  
  26. {
  27. int rc;
  28. int i;
  29.  
  30. if ((rc = InitMap (PartSize / PAGESIZE)) != SUCCESS)
  31.   {
  32.   PRINT_DEB ("Couldn't init bitmap", 0L);
  33.   return (rc);
  34.   }
  35.  
  36. NumSlotsInCache = CurrentConfig.WriteBuffer / PAGESIZE;
  37. BufSize = NumSlotsInCache * (PAGESIZE + sizeof (BOOL));
  38.  
  39. if (BufSize != NULL)
  40.   {
  41.   if ((WriteCache = AllocMem (BufSize, MEMF_PUBLIC)) == NULL)
  42.     {
  43.     PRINT_DEB ("Not enough memory for write cache", 0L);
  44.     return (ERR_NOT_ENOUGH_MEM);
  45.     }
  46.  
  47.   EntryValid = (BOOL*) (WriteCache + NumSlotsInCache * PAGESIZE);
  48.   for (i = 0; i < NumSlotsInCache; i++)
  49.     *(EntryValid + i) = FALSE;
  50.  
  51.   FirstSlot = AllocMultipleSlots (&NumSlotsInCache);
  52.   NumSlotsUsedInCache = 0;
  53.   }
  54.  
  55. NumSlotsUsed = 0;
  56. return (SUCCESS);
  57. }
  58.  
  59. /************************************************************************/
  60.  
  61. void KillCache (void)
  62.  
  63. {
  64. if (BufSize != NULL)
  65.   FreeMem (WriteCache, BufSize);
  66.  
  67. KillMap ();
  68. }
  69.  
  70. /************************************************************************/
  71.  
  72. BOOL ReadPage (ULONG slot, struct TrapStruct *ThisFault)
  73.  
  74. {
  75. if (BufSize != NULL)
  76.   {
  77.   /* Check if this page is in the cache */
  78.   if (slot >= FirstSlot && slot < FirstSlot + NumSlotsInCache &&
  79.       EntryValid [slot - FirstSlot])
  80.     {
  81.     /* PRINT_DEB ("Reading page from write cache", 0L); */
  82.     CopyMemQuick (WriteCache + (slot - FirstSlot) * PAGESIZE,
  83.                   (APTR)ThisFault->PhysAddr, PAGESIZE);
  84.     return (READY);
  85.     }
  86.   }
  87.  
  88. ReadSinglePage (slot, ThisFault);
  89. LastAccessed = slot;
  90. return (IN_PROGRESS);
  91. }
  92.  
  93. /************************************************************************/
  94.  
  95. BOOL WritePage (ULONG slot, struct TrapStruct *ThisFault)
  96.  
  97. {
  98. if (BufSize != NULL)
  99.   {
  100.   if (slot >= FirstSlot && slot < FirstSlot + NumSlotsInCache)
  101.     {
  102.     /* PRINT_DEB ("Putting page in write cache", 0L); */
  103.     CopyMemQuick ((APTR)ThisFault->PhysAddr, 
  104.                   WriteCache + (slot - FirstSlot) * PAGESIZE, PAGESIZE);
  105.     if (!EntryValid [slot - FirstSlot])
  106.       NumSlotsUsedInCache++;
  107.     EntryValid [slot - FirstSlot] = TRUE;
  108.     return (READY);
  109.     }
  110.  
  111.   PRINT_DEB ("WritePage: Page outside cache bounds (slot %ld)?!?", slot);
  112. #ifdef DEBUG
  113.   ColdReboot ();
  114. #endif
  115.   }
  116.  
  117. if (!ResetInProgress)
  118.   WriteSinglePage (slot, ThisFault);
  119. LastAccessed = slot;
  120. return (IN_PROGRESS);
  121. }
  122.  
  123. /************************************************************************/
  124.  
  125. ULONG AllocPageOnDisk (void)
  126.  
  127. {
  128. NumSlotsUsed++;
  129.  
  130. if (BufSize != NULL)
  131.   {
  132.   ULONG i;
  133.  
  134.   for (i = 0; i < NumSlotsInCache; i++)
  135.     {
  136.     if (!EntryValid [i])
  137.       return (i + FirstSlot);
  138.     }
  139.  
  140.   /* If we have arrived here the cache is currently full, so it has
  141.    * to be flushed.
  142.    */
  143.   FlushCache ();
  144.   for (i = 0; i < NumSlotsInCache; i++)
  145.     {
  146.     if (!EntryValid [i])
  147.       return (i + FirstSlot);
  148.     }
  149.  
  150.   PRINT_DEB ("AllocPageOnDisk: Didn't find place in write buffer", 0L);
  151. #ifdef DEBUG
  152.   ColdReboot ();
  153. #endif  
  154.   }
  155.  
  156. return (AllocSlotNextTo (LastAccessed));
  157. }
  158.  
  159. /************************************************************************/
  160.  
  161. void FreePageOnDisk (ULONG slot)
  162.  
  163. {
  164. NumSlotsUsed--;
  165.  
  166. if (BufSize != NULL)
  167.   {
  168.   if (slot >= FirstSlot && slot < FirstSlot + NumSlotsInCache)
  169.     {
  170.     EntryValid [slot - FirstSlot] = FALSE;
  171.     NumSlotsUsedInCache--;
  172.     return;
  173.     }
  174.   }
  175.  
  176. FreeSlot (slot);
  177. }
  178.  
  179. /************************************************************************/
  180.  
  181. PRIVATE void FlushCache (void)
  182.  
  183. {
  184. LONG FirstPage,
  185.      LastPage,
  186.      i;
  187.  
  188. PRINT_DEB ("Flushing cache", 0L);
  189.  
  190. /* Search for the first and the last valid page and write all pages
  191.  * in between.
  192.  */
  193.  
  194. for (FirstPage = 0; FirstPage < NumSlotsInCache; FirstPage++)
  195.   {
  196.   if (EntryValid [FirstPage])
  197.     break;
  198.   }
  199.  
  200. for (LastPage = NumSlotsInCache - 1; LastPage >= 0; LastPage--)
  201.   {
  202.   if (EntryValid [LastPage])
  203.     break;
  204.   }
  205.  
  206. if (FirstPage > LastPage)     /* Cache empty */
  207.   return;
  208.  
  209. if (!ResetInProgress)
  210.   WriteMultiplePages (FirstSlot + FirstPage, WriteCache + FirstPage * PAGESIZE,
  211.                       LastPage - FirstPage + 1);
  212.  
  213. /* Free unused slots */
  214. for (i = 0; i < NumSlotsInCache; i++)
  215.   {
  216.   if (!EntryValid [i])
  217.     FreeSlot (i + FirstSlot);
  218.   else
  219.     EntryValid [i] = FALSE;
  220.   }
  221.  
  222. NumSlotsInCache = BufSize / (PAGESIZE + sizeof (BOOL));
  223. FirstSlot = AllocMultipleSlots (&NumSlotsInCache);
  224.  
  225. NumSlotsUsedInCache = 0;
  226. }
  227.  
  228. /************************************************************************/
  229.  
  230. ULONG SlotsUsed (void)
  231.  
  232. {
  233. return (NumSlotsUsed);
  234. }
  235.  
  236. /************************************************************************/
  237.  
  238. void AllocNewCache (void)
  239.  
  240. {
  241. /* This function is executed by a separate task which is created only for 
  242.  * this function. Because it can lead to difficulties, if the VM_Manager
  243.  * or the pagehandler have to allocate memory during runtime this approach
  244.  * has been chosen.
  245.  * This function reads the desired buffer size from a global variable named
  246.  * 'DesiredWriteBufferSize', tries to allocate enough memory, sends a message to
  247.  * the pagehandler and exits.
  248.  * The pagehandler then installs this buffer and frees the old one.
  249.  */
  250.  
  251. ULONG MyBufSize;
  252. struct VMMsg *NewWriteBufMsg;
  253. char *NewWriteBuf;
  254.  
  255. if ((NewWriteBufMsg = AllocMem (sizeof (struct VMMsg), MEMF_PUBLIC)) == NULL)
  256.   /* Cannot do anything about it. Just leave it the way it was */
  257.   return;
  258.  
  259. MyBufSize = (DesiredWriteBufferSize / PAGESIZE) * (PAGESIZE + sizeof (BOOL));
  260.  
  261. if (MyBufSize != NULL)
  262.   {
  263.   if ((NewWriteBuf = AllocMem (MyBufSize, MEMF_PUBLIC)) == NULL)
  264.     {
  265.     FreeMem (NewWriteBufMsg, sizeof (struct VMMsg));
  266.     return;
  267.     }
  268.   }
  269. else
  270.   NewWriteBuf = NULL;
  271.  
  272. NewWriteBufMsg->VMCommand = VMCMD_NewWriteBuffer;
  273. NewWriteBufMsg->ReplySignal = 0;
  274. NewWriteBufMsg->NewWriteBuffer = NewWriteBuf ;
  275. NewWriteBufMsg->NewWriteBufferSize = MyBufSize;
  276. PutMsg (PageHandlerPort, (struct Message*)NewWriteBufMsg);
  277. }
  278.  
  279. /************************************************************************/
  280.  
  281. void NewCache (char *buffer, ULONG size)
  282.  
  283. {
  284. int i;
  285.  
  286. if (BufSize != NULL)
  287.   {
  288.   FlushCache ();
  289.  
  290.   /* Free unused slots */
  291.   for (i = 0; i < NumSlotsInCache; i++)
  292.     FreeSlot (i + FirstSlot);
  293.  
  294.   FreeMem (WriteCache, BufSize);
  295.   }
  296.  
  297. BufSize = size;
  298. WriteCache = buffer;
  299. if (BufSize != 0L)
  300.   {
  301.   NumSlotsInCache = BufSize / (PAGESIZE + sizeof (BOOL));
  302.   EntryValid = (BOOL*) (WriteCache + NumSlotsInCache * PAGESIZE);
  303.   for (i = 0; i < NumSlotsInCache; i++)
  304.     *(EntryValid + i) = FALSE;
  305.   
  306.   FirstSlot = AllocMultipleSlots (&NumSlotsInCache);
  307.   NumSlotsUsedInCache = 0;
  308.   }
  309. }
  310.